package com.zide.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zide.auth.domain.entity.platform.PlatformRole;
import com.zide.auth.domain.entity.platform.PlatformUser;
import com.zide.auth.mapper.platform.PlatformRoleMapper;
import com.zide.auth.utils.ZiDeContext;
import com.zide.auth.vo.TreeSelect;
import com.zide.common.constant.UserConstants;
import com.zide.common.core.text.Convert;
import com.zide.common.exception.ServiceException;
import com.zide.common.utils.StringUtils;
import com.zide.common.utils.spring.SpringUtils;
import com.zide.auth.domain.entity.platform.dept.PlatformDept;
import com.zide.platform.mapper.PlatformDeptMapper;
import com.zide.platform.service.PlatformDeptService;
import com.zide.platform.vo.result.dept.PlatformDeptResultVO;
import com.zide.platform.vo.search.dept.PlatformDeptSearchVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 石添添
 * @description
 * @date 2024-09-22 16:04
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PlatformDeptServiceImpl implements PlatformDeptService {
    private final PlatformDeptMapper deptMapper;
    private final PlatformRoleMapper roleMapper;
    
    @Override
    public List<PlatformDeptResultVO> selectDeptList(PlatformDeptSearchVO searchVO) {
        LambdaQueryWrapper<PlatformDept> wrapper = new LambdaQueryWrapper<>();
        if(ObjectUtil.isNotNull(searchVO.getId())) {
            wrapper.eq(PlatformDept::getId,searchVO.getId());
        }
        if(ObjectUtil.isNotNull(searchVO.getParentId())) {
            wrapper.eq(PlatformDept::getParentId,searchVO.getParentId());
        }
        if(StrUtil.isNotEmpty(searchVO.getDeptName())) {
            wrapper.like(PlatformDept::getDeptName,searchVO.getDeptName());
        }
        if(ObjectUtil.isNotNull(searchVO.getStatus())) {
            wrapper.eq(PlatformDept::getStatus,searchVO.getStatus());
        }
        wrapper.orderByAsc(PlatformDept::getParentId).orderByAsc(PlatformDept::getSorts);
        List<PlatformDept> PlatformDeptList = deptMapper.selectList(wrapper);

        return BeanUtil.copyToList(PlatformDeptList,PlatformDeptResultVO.class);
    }

    @Override
    public List<TreeSelect> selectDeptTreeList(PlatformDeptSearchVO searchVO) {
        List<PlatformDeptResultVO> depts = selectDeptList(searchVO);
        List<PlatformDept> PlatformDepts = BeanUtil.copyToList(depts, PlatformDept.class);
        return buildDeptTreeSelect(PlatformDepts);
    }

    @Override
    public List<PlatformDept> buildDeptTree(List<PlatformDept> depts) {
        List<PlatformDept> returnList = new ArrayList<PlatformDept>();
        List<Long> tempList = depts.stream().map(PlatformDept::getId).collect(Collectors.toList());
        for (PlatformDept dept : depts) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = depts;
        }
        return returnList;
    }

    @Override
    public List<TreeSelect> buildDeptTreeSelect(List<PlatformDept> depts) {
        List<PlatformDept> deptTrees = buildDeptTree(depts);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    @Override
    public List<Long> selectDeptListByRoleId(Long roleId) {
        PlatformRole role = roleMapper.selectRoleById(roleId);
        return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
    }

    @Override
    public PlatformDept selectDeptById(Long deptId) {
        return deptMapper.selectById(deptId);
    }

    @Override
    public int selectNormalChildrenDeptById(Long deptId) {
        return deptMapper.selectNormalChildrenDeptById(deptId);
    }

    @Override
    public boolean hasChildByDeptId(Long deptId) {
        int result = deptMapper.hasChildByDeptId(deptId);
        return result > 0;
    }

    @Override
    public boolean checkDeptExistUser(Long deptId) {
        int result = deptMapper.checkDeptExistUser(deptId);
        return result > 0;
    }

    @Override
    public boolean checkDeptNameUnique(PlatformDept dept) {
        Long deptId = StringUtils.isNull(dept.getId()) ? -1L : dept.getId();
        PlatformDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
        if (StringUtils.isNotNull(info) && info.getId().longValue() != deptId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public void checkDeptDataScope(Long deptId) {
        if (!PlatformUser.isAdmin(ZiDeContext.getPlatformUserId())) {
            PlatformDeptSearchVO dept = new PlatformDeptSearchVO();
            dept.setId(deptId);
            List<PlatformDeptResultVO> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
            if (StringUtils.isEmpty(depts)) {
                throw new ServiceException("没有权限访问部门数据！");
            }
        }
    }

    @Override
    public int insertDept(PlatformDept dept) {
        PlatformDept info = deptMapper.selectById(dept.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
            throw new ServiceException("部门停用，不允许新增");
        }
        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
        return deptMapper.insert(dept);
    }

    @Override
    public int updateDept(PlatformDept dept) {
        PlatformDept newParentDept = deptMapper.selectById(dept.getParentId());
        PlatformDept oldDept = deptMapper.selectById(dept.getId());
        if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept)) {
            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getId();
            String oldAncestors = oldDept.getAncestors();
            dept.setAncestors(newAncestors);
            updateDeptChildren(dept.getId(), newAncestors, oldAncestors);
        }
        int result = deptMapper.updateById(dept);
        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
                && !StringUtils.equals("0", dept.getAncestors())) {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentDeptStatusNormal(dept);
        }
        return result;
    }

    @Override
    public int deleteDeptById(Long deptId) {
        return deptMapper.deleteById(deptId);
    }

    /**
     * 修改该部门的父级部门状态
     *
     * @param dept 当前部门
     */
    private void updateParentDeptStatusNormal(PlatformDept dept) {
        String ancestors = dept.getAncestors();
        Long[] deptIds = Convert.toLongArray(ancestors);
        deptMapper.updateDeptStatusNormal(deptIds);
    }

    /**
     * 修改子元素关系
     *
     * @param deptId       被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
        List<PlatformDept> children = deptMapper.selectChildrenDeptById(deptId);
        for (PlatformDept child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            deptMapper.updateDeptChildren(children);
        }
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<PlatformDept> list, PlatformDept t) {
        // 得到子节点列表
        List<PlatformDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (PlatformDept tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<PlatformDept> getChildList(List<PlatformDept> list, PlatformDept t) {
        List<PlatformDept> tlist = new ArrayList<PlatformDept>();
        Iterator<PlatformDept> it = list.iterator();
        while (it.hasNext()) {
            PlatformDept n = (PlatformDept) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<PlatformDept> list, PlatformDept t) {
        return getChildList(list, t).size() > 0;
    }
}
